package main

import (
	"encoding/json"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
)

type Movie struct {
	Id       int       `json:"id"`
	Title    string    `json:"title"`
	Score    float32   `json:"score"`
	Director *Director `json:"director"`
}

type Director struct {
	FirstName string `json:"firstname"`
	LastName  string `json:"lastname"`
}

// 声明并初始化全局变量 movies
var movies = []Movie{
	{
		Id:    1,
		Title: "The Shawshank Redemption",
		Score: 9.3,
		Director: &Director{
			FirstName: "Frank",
			LastName:  "Darabont",
		},
	},
	{
		Id:    2,
		Title: "The Godfather",
		Score: 9.2,
		Director: &Director{
			FirstName: "Francis",
			LastName:  "Coppola",
		},
	},
	{
		Id:    3,
		Title: "The Dark Knight",
		Score: 9.0,
		Director: &Director{
			FirstName: "Christopher",
			LastName:  "Nolan",
		},
	},
	{
		Id:    4,
		Title: "Pulp Fiction",
		Score: 8.9,
		Director: &Director{
			FirstName: "Quentin",
			LastName:  "Tarantino",
		},
	},
	{
		Id:    5,
		Title: "Schindler's List",
		Score: 8.9,
		Director: &Director{
			FirstName: "Steven",
			LastName:  "Spielberg",
		},
	},
	{
		Id:    6,
		Title: "The Lord of the Rings: The Return of the King",
		Score: 8.9,
		Director: &Director{
			FirstName: "Peter",
			LastName:  "Jackson",
		},
	},
	{
		Id:    7,
		Title: "Fight Club",
		Score: 8.8,
		Director: &Director{
			FirstName: "David",
			LastName:  "Fincher",
		},
	},
	{
		Id:    8,
		Title: "Forrest Gump",
		Score: 8.8,
		Director: &Director{
			FirstName: "Robert",
			LastName:  "Zemeckis",
		},
	},
	{
		Id:    9,
		Title: "Inception",
		Score: 8.8,
		Director: &Director{
			FirstName: "Christopher",
			LastName:  "Nolan",
		},
	},
	{
		Id:    10,
		Title: "Goodfellas",
		Score: 8.7,
		Director: &Director{
			FirstName: "Martin",
			LastName:  "Scorsese",
		},
	},
}

func GetMovies(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(movies)
}

func GetMovie(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	id, err := strconv.Atoi(params["id"])

	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return
	}

	for _, item := range movies {
		if item.Id == id {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(item)
			return
		}
	}
}

func CreateMovie(w http.ResponseWriter, r *http.Request) {

	var movie Movie
	_ = json.NewDecoder(r.Body).Decode(&movie)
	movie.Id = len(movies) + 1
	movies = append(movies, movie)
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(movie)
}

func UpdateMovie(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)

	id, err := strconv.Atoi(params["id"])

	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return
	}

	for i, item := range movies {
		if item.Id == id {
			movies = append(movies[:i], movies[i+1:]...)
			var movie Movie
			_ = json.NewDecoder(r.Body).Decode(&movie)
			movie.Id = id
			movies = append(movies, movie)
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(movie)
		}
	}

}

func DeleteMovie(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	id, err := strconv.Atoi(params["id"])

	if err != nil {
		http.Error(w, "Invalid ID", http.StatusBadRequest)
		return
	}

	for i, item := range movies {
		if item.Id == id {
			movies = append(movies[:i], movies[i+1:]...)
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(movies)
			return
		}
	}

}

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/movies", GetMovies).Methods("GET")
	r.HandleFunc("/movies/{id}", GetMovie).Methods("GET")
	r.HandleFunc("/movies", CreateMovie).Methods("POST")
	r.HandleFunc("/movies/{id}", UpdateMovie).Methods("PUT")
	r.HandleFunc("/movies/{id}", DeleteMovie).Methods("DELETE")

	http.ListenAndServe(":8888", r)
}
